/**
*  Copyright (c) 2011, Alex Theodoridis
*  All rights reserved.

*  Redistribution and use in source and binary forms, with
*  or without modification, are permitted provided that the
*  following conditions are met:
*  Redistributions of source code must retain the above
*  copyright notice, this list of conditions and the following disclaimer.
*  Redistributions in binary form must reproduce the above
*  copyright notice, this list of conditions and the following
*  disclaimer in the documentation and/or other materials
*  provided with the distribution.

*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS
*  AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
*  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
*  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
*  IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
*  OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
*  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
*  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
*  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
*  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
*  ANY WAY OUT OF THE USE OF THIS SOFTWARE,
*  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
*/

#ifndef SigmaEquationH
#define SigmaEquationH
#include <NeuralNetwork/Neuron/Equation/IEquation.h>
#include <NeuralNetwork/NNException.h>
#include <math.h>

namespace nn {

    /**
     * Sigmoid function implementation.
     * Used by not-linear neural networks.
     */
    template<class Var>
    class SigmaEquation : public IEquation<Var> {
    private:
        /**
         * Slope value.
         */
        Var _slope;

    public:

        /**
         * Empty constructor.
         */
        SigmaEquation() {
            _slope = 1.0f;
        }

        /**
         * Will calculate the equation
         * for the given input value.
         * @return the calculation result.
         */
        Var calculateEquation ( const Var& neuronWeight, const std::map<unsigned int, NeuronInput<Var> >& inputs ) {
            Var sum = 0.0f;
            typename std::map<unsigned int, NeuronInput<Var> >::const_iterator curInput;
            for ( curInput = inputs.begin(); curInput != inputs.end(); curInput++ ) {
                sum = sum + curInput->second.getInputWeight() * curInput->second.getValue();
            }

            sum = sum + neuronWeight;
            Var tmp ( _slope * sum );
            Var tmp2 = tmp * ( -1.0f );
            return Var ( 1.0f ) / ( Var ( 1.0f ) + exp ( tmp2 ) );
        }

        /**
         * Will calculate the differential
         * for current equation.
         * @param input the input value for calculation.
         * @return result of calculation.
         */
        Var calculateDifferential ( const Var& input ) {
            return _slope * input * ( Var ( 1.0f ) - input );
        }

        /**
         * Will set the slope for
         * calculations.
         * @param slope the slope value.
         */
        bool setSlope ( const Var& slope ) {
            if ( slope < Var ( 0.0f ) ) {
                return false;
            }

            _slope = slope;
            return true;
        }

        /**
         * Will return the
         * current value of slope.
         * @return slope.
         */
        Var getSlope ( void ) {
            return _slope;
        }

        /**
         * Destructor.
         */
        virtual ~SigmaEquation() throw () {
        }
    };

}

#endif
// kate: indent-mode cstyle; space-indent on; indent-width 4; 
